home *** CD-ROM | disk | FTP | other *** search
- //
- // Event.m
- // Copyright (c) 1988, 1989, 1990 by Jiro Nakamura
- // All rights reserved
- //
- // Implementation definition of class Event. Event handles
- // the database management of Cassandra.
- //
- // RCS Information
- // Revision Number-> $Revision: 2.11 $
- // Last Revised-> $Date: 91/11/01 17:24:00 $
- //
- static char rcsid[] = "$Id: Event.m,v 2.11 91/11/01 17:24:00 jiro Exp Locker: jiro $";
-
- #import "Event.h"
- #import <objc/objc.h>
- #import <strings.h>
- #import <appkit/Panel.h> /* for NXRunAlertPanel */
- #import "cass.h"
- #import "calendar.h"
- #import "Global.h"
- #import "misc.h"
- #import <sys/types.h>
- #import <sys/stat.h>
-
- // Defining DEBUG for Event can sometimes get very screen messy
- // since Cassandra uses it so often
- #ifdef DEBUG
- #undef DEBUG
- #define DEBUG2
- #endif
-
- #define VERSION_15 1
- #define EVENT_VERSION 1
-
- int fgeti( int *i , FILE *fp)
- {
- char buffer[10];
- if( fgets(buffer, 10, fp) == NULL || strlen( buffer ) < 1)
- {
- *i = 0;
- return -1;
- }
- *i = atoi(buffer);
- return 0;
- }
-
-
- @implementation Event
-
- + newAt:(const char*) eFile
- {
- self = [super new];
- strcpy(eventFile,eFile);
-
- eventType = 0;
- priority = 50;
- destroy = snoozeNo = snoozeInt =0;
- anniversary = annvSpecial = 0;
- present = next = previous = 0;
-
- strcpy(alarmSound, ALARMSOUND);
- strcpy(msg,"empty");
- return self;
- }
-
- + new
- {
- fprintf(stderr,"This should never be called!");
- self = [super new];
- return self;
- }
-
- - free
- {
- #ifdef DEBUG
- fprintf(stderr,"Event.m:Free ->Closing event!\n");
- #endif
- [super free];
- return nil;
- }
-
- //
- //
- // Messages that affect how the file is stored on disk
- //
- //
-
- - default: sender
- {
- present = 0;
- previous = next = -1;
- destroy = 1;
- anniversary = annvSpecial = snoozeInt = snoozeNo = priority = 0;
- ts.tm_sec = ts.tm_min = ts.tm_hour = 0;
- ts.tm_mday = ts.tm_mon = ts.tm_year = 0;
- ts.tm_wday = ts.tm_yday = ts.tm_isdst = 0;
- alarmAction = playSound;
-
- strcpy(msg, "");
- strcpy(alarmSound,[global alarmSound]);
- return self;
- }
-
-
- - readEvent: (EFileLink) here /* read itself from the event file */
- {
- FILE * source;
- static char errormsg[128], buffer[255];
- char *tp; // temporary pointer
- struct stat statBuf;
- int tmp;
-
- #ifdef DEBUG
- fprintf(stderr, "------------------------\n"
- "[Event readEvent: %d]\n",here);
- #endif
-
- if( here < 0)
- {
- NXRunAlertPanel("File Seek Error",
- "Cannot seek to a negative number.",
- "OK",NULL,NULL);
- strcpy(msg, "Illegal event/link value....");
- return nil;
- }
-
- /* Let's first check to make sure we aren't reading an empty file */
- stat( eventFile, &statBuf);
- if( statBuf.st_size < 100) // It can not be this short
- {
- strcpy(msg, CASSANDRAVERSION);
- next = previous = 0;
- present = here;
- [self writeEvent: here];
- fprintf(stderr, "%s: Event list not initialized. "
- "Initializing....\n",
- PROGNAME);
- return nil;
- }
-
- sprintf(errormsg, "Error occured while trying to read event file %s",
- eventFile);
- source = fileOpen(eventFile, "r+",errormsg);
-
- sprintf(errormsg, "An fatal error occured when we were trying "
- "to seek to event number %d for reading event "
- "file %s.\n This program has crashed.",
- here, eventFile);
- if( fileSeek(source, here, errormsg) == NULL)
- {
- next = previous = -1;
- present = here;
- return nil;
- }
-
- fgeti(&present, source);
- if( present != here)
- {
- fprintf(stderr,
- "%s: File header gives %d instead of %d.\n"
- "%s: We've most probably run out off the end of %s.\n"
- PROGNAME ,present, here,
- PROGNAME, [global eventFile]);
- next = previous = -1;
- present = here;
- fclose(source);
- return nil;
- }
- else
- {
- fgeti(&previous, source);
- fgeti(&next, source);
- }
-
- fgeti( &tmp, source);
- version = tmp / 100;
- eventType = tmp % 100;
- fgets( buffer, 10, source);
-
- #ifdef DEBUG2
- fprintf(stderr, "Version = %d\n", version);
- #endif
-
- fgeti( &priority, source);
-
- switch( version)
- {
- case VERSION_15:
- fgeti( &annvSpecial, source);
- fgeti( &anniversary, source);
- break;
- case 0:
- default:
- fgeti( &destroy, source);
- fgeti( &anniversary, source);
- break;
- }
- #ifdef DEBUG2
- fprintf(stderr, "Anniversary = %d\n", anniversary);
- fprintf(stderr, "AnniversarySpecial = %d\n", annvSpecial);
- #endif
-
- fgeti( &snoozeNo, source);
- fgeti( &snoozeInt, source);
-
- fgets( buffer, 10, source);
- fgets( buffer, 10, source);
-
- fgeti( &ts.tm_sec, source);
- fgeti( &ts.tm_min, source);
- fgeti( &ts.tm_hour, source);
- fgeti( &ts.tm_mday, source);
- fgeti( &ts.tm_mon, source);
- fgeti( &ts.tm_year, source);
-
- switch( version)
- {
- case VERSION_15:
- fgeti( &duration, source);
- fgeti( &tmp, source);
- alarmAction = tmp;
- fgeti( &ts.tm_isdst, source);
- break;
- case 0:
- default:
- fgeti( &ts.tm_wday, source);
- fgeti( &ts.tm_yday, source);
- fgeti( &ts.tm_isdst, source);
- break;
- }
-
- fgets( alarmSound, 100, source); // We gotta strip the final
- tp = rindex( alarmSound, '\n'); // newline and replace it with
- if( tp != NULL) // a NULL character.
- *tp = '\0';
-
- fgets( buffer, 10, source);
- fgets( buffer, 10, source);
- fgets( buffer, 10, source);
- fgets( buffer, 10, source);
-
- fgets(msg,MESSAGE_SIZE,source);
-
- ts.tm_wday = wday(ts.tm_mday, ts.tm_mon+1, 1900+ts.tm_year);
- ts.tm_yday = yday(ts.tm_mday, ts.tm_mon+1, ts.tm_year+1900);
-
- fixTmStructure( &ts);
-
- switch( version)
- {
- case VERSION_15:
- break;
-
- default:
- case 0:
- switch( alarmSound[0] )
- {
- case '-': // don't play alarm
- strcpy(buffer, alarmSound);
- strcpy(alarmSound, buffer+1);
- alarmAction = nothing;
- break;
- case '?':
- strcpy(buffer, alarmSound);
- strcpy(alarmSound, buffer+1);
- alarmAction = playAndDeleteSound;;
- break;
- case '!':
- strcpy(buffer, alarmSound);
- strcpy(alarmSound, buffer+1);
- alarmAction = runCommand;
- break;
- }
- break;
- }
-
-
- if( msg[0] == ';')
- {
- char buf[MESSAGE_SIZE];
-
- strcpy(buf, msg);
- strcpy(msg, buf+1);
- showMessage = FALSE;
- }
- else
- showMessage = TRUE;
-
- fclose(source);
- return self;
- }
-
- - firstEvent
- {
- #ifdef DEBUG
- fprintf(stderr,"Reading in the first event.\n");
- #endif
-
- [self readEvent : 0];
- if( [self next] == 0)
- return self;
- [self readEvent : [self next]];
- return self;
- }
-
- - writeEvent: (EFileLink) here
- /* write itself into the event file using present as its index */
- {
- FILE *source;
- char errormsg[256], bufAlarm[256], bufMessage[256];
-
- if( here < 0)
- {
- NXRunAlertPanel( "Write Error",
- "We can't write to a negative event number.",
- "OK",NULL,NULL);
- return nil;
- }
-
- #ifdef DEBUG
- fprintf(stderr, "------------------------\n"
- "[Event writeEvent: %d]: Opening event with "
- "<%s>!\n",here, eventFile);
- #endif
-
- sprintf(errormsg, "Fatal error when trying to write to event file %s",
- eventFile);
- source = fileOpen(eventFile, "r+",errormsg);
-
- sprintf(errormsg, "%s: An fatal error occured when we were trying to "
- "seek to event number %d for writing in event file %s.\n"
- " This program has crashed.", PROGNAME, here, eventFile);
- fileSeek(source, here, errormsg);
-
- present = here;
-
- if( ts.tm_year > 1900)
- ts.tm_year -= 1900;
-
- strcpy(bufAlarm, alarmSound);
-
- if( showMessage == FALSE)
- {
- strcpy(bufMessage, ";");
- strcat(bufMessage, msg);
- }
- else
- strcpy(bufMessage, msg);
-
- #ifdef DEBUG2
- fprintf(stderr, "wAnniversary = %d\n", anniversary);
- fprintf(stderr, "wAnniversarySpecial = %d\n", annvSpecial);
- #endif
-
-
- if(fprintf( source,
- "%d\n%d\n%d\n"
- "%d\n\n"
- "%d\n%d\n%d\n"
- "%d\n%d\n"
- "\n\n"
- "%d\n%d\n%d\n"
- "%d\n%d\n%d\n"
- "%d\n%d\n%d\n"
- "%s\n\n"
- "\n\n\n"
- "%s\n",
- present, previous, next,
- EVENT_VERSION * 100 + eventType,
- priority, annvSpecial, anniversary,
- snoozeNo, snoozeInt,
- ts.tm_sec, ts.tm_min, ts.tm_hour,
- ts.tm_mday, ts.tm_mon, ts.tm_year,
- duration, alarmAction, ts.tm_isdst,
- bufAlarm, bufMessage) == -1)
- {
- fprintf(stderr, "%s: Event.m: Error occured writing file.",
- PROGNAME);
- strcpy(msg, "Error occured in writing out Elink number.\n\n");
- fclose(source);
- return nil;
- }
-
- #ifdef DEBUG
- fprintf(stderr, "%s: Wrote out Efilelink.\n Here=%d,"
- "Previous = %d, Next=%d\n", PROGNAME,
- here, previous, next);
- fprintf(stderr, "%s: Date: time = %d:%d, day= %d, "
- "month = %d, year = %d.\n\n",PROGNAME,
- ts.tm_hour, ts.tm_min, ts.tm_mday, ts.tm_mon,
- ts.tm_year);
- fprintf(stderr,"%s: AlarmSound =%s\n", PROGNAME, bufAlarm);
- #endif
-
- fclose(source);
- return self;
- }
-
- - (EFileLink) insertEvent
- {
- return [self insertEventFrom : 1];
- }
-
-
-
- /* insert itself into the file with current day as index */
- /* and starting from <here> in searching for a open deleted space */
- - (EFileLink) insertEventFrom : (EFileLink) here
- {
- id event, step;
- int loop;
-
-
- // First things first, we must check the format of our time structure
- // since we have given other functions full freedom to scew it up
-
- fixTmStructure( &ts);
-
- event = [Event newAt:eventFile];
- step = [Event newAt:eventFile];
- [event readEvent:0];
- for( [event readEvent: [event next]];
- [event present] != 0 && timeCompare([event time], &ts) < 0;
- [event readEvent:[event next]])
- {
- #ifdef DEBUG
- fprintf(stderr, "From %d looping onto %d\n",
- [event present],[event next]);
- #endif
- }
-
-
- if( timeCompare([event time], &ts) == 0 )
- {
- if( NXRunAlertPanel("Scheduling Conflict?",
- "You have another "
- "scheduled event at that time. Should I insert this "
- "event anyway?", "Insert anyway", "Cancel it",
- NULL) == 0 )
- [event free];
- [step free];
- return 0;
- }
-
-
-
- #ifdef DEBUG
- fprintf(stderr, "inserting between %d <- event -> %d.\n",
- [event previous], [event present]);
- #endif
-
- previous = [event previous];
- next = [event present];
-
- [step setNext: 0];
- for( loop = here; !([step next] == -1 && [step previous] == -1); [step readEvent: loop++])
- {
- #ifdef DEBUG
- fprintf(stderr, "reading at %d.\n",loop);
- #endif
- }
-
- present = [step present];
-
- [self writeEvent: present];
-
- [step readEvent: previous];
- [step setNext : present];
- [step writeEvent:previous];
-
- [step readEvent: next];
- [step setPrevious : present];
- [step writeEvent:next];
-
- [step free];
- [event free];
- #ifdef DEBUG
- fprintf(stderr,"successfully inserted %d <- %d -> %d\n\n",[self previous],[self present], [self next]);
- #endif
-
-
- return( [self present] );
- }
-
- /* delete itself from the file with present as index */
- - deleteEvent : (EFileLink) here
- {
- id previousEvent, nextEvent;
-
- #ifdef DEBUG
- fprintf(stderr, "Deleting <%d>\n\n",here);
- #endif
-
- if( here <= 0)
- {
- NXRunAlertPanel(NULL,"You cannot delete link 0 or below. OK?",
- "Shucks...",NULL,NULL);
- fprintf(stderr,"Can't delete the header. Here = %d.\n\n",
- here);
- return nil;
- }
-
- previousEvent= [Event newAt: eventFile];
- nextEvent = [Event newAt:eventFile];
-
- [previousEvent readEvent :here];
- if( ( [previousEvent previous] == -1 ) ||
- ( [previousEvent next] == -1 ) )
- {
- /* link was already deleted, so we can't delete it..... */
- strcpy(msg, "Can't delete link because it's already been "
- "deleted!?!\n\n");
- return nil;
- }
-
- /* Set the previous_link of the next link */
- /* to the one of the previous one */
- [nextEvent readEvent :[previousEvent next]];
- [nextEvent setPrevious : [previousEvent previous]];
- [nextEvent writeEvent :[previousEvent next]];
-
- /* do the same confusing spiel for previous */
- [nextEvent readEvent :[previousEvent previous] ];
- [nextEvent setNext : [previousEvent next]];
- [nextEvent writeEvent :[previousEvent previous] ];
-
- /* cancel out the header to finally kill it */
- /* and write it out */
- [previousEvent setNext : -1];
- [previousEvent setPrevious :-1];
- [previousEvent writeEvent :here];
-
- #ifdef DEBUG
- fprintf(stderr, "Record %d successfully deleted.\n\n",
- here);
- #endif
-
- [previousEvent free];
- [nextEvent free];
- return self;
- }
-
- /* delete if it is not an anniversary event, update otherwise */
- - (int) murderEvent : (EFileLink) here
- {
- Event *event;
-
- #ifdef DEBUG
- fprintf(stderr,"Arrggh! Help! I'm getting murdered! "
- "(says Event <%d>)\n\n",
- here);
- #endif
-
- event = [Event newAt :eventFile];
- [event readEvent : here]; // Read the event in
- [event deleteEvent : here]; // Delete the event
-
- if( (int) ([event anniversary]/100) == 0) // No anniversary
- return -1;
-
- [event setTime: fixAnniversary( [event time], [event anniversary],
- [event annvSpecial])];
- // Fix the next event time and reinsert it
-
- // Use the same EFilelink space that we deleted, this saves
- // us time and maybe some confusion
- return( [event insertEventFrom:here] );
- }
-
-
- - setMday : (int) x { ts.tm_mday = x; return self; }
- - setMon: (int) x { ts.tm_mon = x; return self; }
- - setYear: (int) x { ts.tm_year = x; return self; }
-
- - setHour: (int) x { ts.tm_hour = x; return self; }
- - setMin: (int) x { ts.tm_min = x; return self; }
- - setSec: (int) x { ts.tm_sec = x; return self; }
- - setDestroy : (int) dst { destroy = dst; return self; }
- - setAnniversary : (int) anv { anniversary = anv; return self; }
- - setAnnvSpecial : (int) anvS { annvSpecial = anvS; return self; }
- - setSnoozeNo : (int) sn { snoozeNo = sn; return self; }
- - setSnoozeInt : (int) si { snoozeInt = si; return self; }
- - setPriority : (int) si { priority = si; return self; }
- - setAlarmSound : (char *) aS { strcpy(alarmSound,aS); return self; }
- - setShowMessage: (BOOL) aFlag { showMessage = aFlag; return self; }
- - setMessage : (char *) message { strcpy( msg, message); return self; }
- - setWday : (int) wd { ts.tm_wday = wd; return self; }
- - setYday : (int) yd { ts.tm_yday = yd; return self; }
- - setPresent : (EFileLink) apresent { present = apresent; return self; }
- - setPrevious : (EFileLink) aprevious { previous =aprevious; return self; }
- - setNext : (EFileLink) anext { next = anext; return self; }
- - setTime : (struct tm *) time { ts = *time; return self; }
-
-
- - setPlayAlarm: (BOOL) aFlag { alarmAction = playSound; return self; }
- - setMailPerson:(BOOL) aFlag { alarmAction = mailPerson; return self; }
- - setRunCommand: (BOOL) aFlag { alarmAction = runCommand; return self; }
- - setDeleteSound: (BOOL) aFlag { alarmAction = playAndDeleteSound;
- return self; }
-
- - setAlarmAction: (int) aa { alarmAction = aa; return self; }
-
- - (EFileLink) present { return present; }
- - (EFileLink) previous { return previous; }
- - (EFileLink) next { return next; }
-
- - (char *) message { return msg; }
- - (char *) alarmSound { return alarmSound; }
-
- - (BOOL) deleteSound { return alarmAction == playAndDeleteSound; }
- - (BOOL) playAlarm { return (alarmAction == playAndDeleteSound ||
- alarmAction == playSound) ; }
- - (BOOL) runCommand { return alarmAction == runCommand; }
- - (BOOL) mailPerson { return alarmAction == mailPerson; }
- - (BOOL) showMessage { return showMessage; }
-
- - (int) alarmAction { return alarmAction; }
-
- - (int) anniversary { return anniversary; }
- - (int) annvSpecial { return annvSpecial; }
- - (int) destroy { return destroy; }
- - (int) hour { return (ts.tm_hour); }
- - (int) mday; { return( ts.tm_mday); }
- - (int) min { return(ts.tm_min); }
- - (int) mon { return (ts.tm_mon); }
- - (int) priority { return priority; }
- - (int) sec { return(ts.tm_sec); }
- - (int) snoozeInt { return snoozeInt; }
- - (int) snoozeNo { return snoozeNo; }
- - (int) wday { return ts.tm_wday; }
- - (int) yday { return ts.tm_yday; }
- - (int) year { return (ts.tm_year); }
-
- - (struct tm *) time { return &ts; }
-
- @end
-
-
- struct tm *fixAnniversary( struct tm *time, int mode, int sub)
- {
- #ifdef DEBUG
- fprintf(stderr,"Fixing weekly special: %s, %d, %d\n", ascMyTime(time, YES, NO),
- mode, sub);
- #endif
-
- switch( (int) mode / 100)
- {
- /* Don't worry about overflows as we add intervals to */
- /* our dates, insertEvent is smart enough to handle it */
- case 0:
- return time; /* No anniversary */
- case 1: /* If it is a day anniversary */
- time->tm_mday+= (mode - 100);
- break;
- case 2: /* Weekly anniversary */
- time -> tm_mday += ((mode - 200) * 7 );
- break;
- case 3: /* Monthly anniversary */
- time-> tm_mon += (mode - 300);
- break;
- case 4: /* Yearly anniversary */
- time -> tm_year += (mode - 400);
- break;
- case 5: /* Special weekly */
- default:
- fprintf(stderr,
- "%s: I do not recognize "
- "anniversary event: %d.\n",
- PROGNAME,
- mode);
- return time;
- }
-
- fixTmStructure( time);
- return time;
- }
-
-
-